using System;
using System.Text;
using System.Data;
using Antu.Core.Services;

namespace Antu.Core.Ajax
{
    /// <summary>
    /// Provides methods to serialize and deserialize a Enum object.
    /// </summary>
    public class EnumConverter : AbstractJavascriptConverter
    {
        SerializerService _SerializerService = (SerializerService)ServiceManager.Manager.GetService(typeof(SerializerService));
        /// <summary>
        /// Initializes a new instance of the <see cref="EnumConverter"/> class.
        /// </summary>
        public EnumConverter()
            : base()
        {
            serializabletypeslist = new Type[] {
				typeof(Enum)
			};
            deserializabletypeslist = serializabletypeslist;
        }

        /// <summary>
        /// Converts a .NET object into a JSON string.
        /// </summary>
        /// <param name="o">The object to convert.</param>
        /// <returns>Returns a JSON string.</returns>
        public override string Serialize( object o )
        {
            StringBuilder sb = new StringBuilder();
            Serialize( o , sb );
            return sb.ToString();
        }

        /// <summary>
        /// Serializes the specified o.
        /// </summary>
        /// <param name="o">The o.</param>
        /// <param name="sb">The sb.</param>
        public override void Serialize( object o , StringBuilder sb )
        {
            // this.SerializeValue(Decimal.GetBits(d), sb);

            // The following code is not correct, but while JavaScript cannot
            // handle the decimal value correct we are using double instead.

            _SerializerService.Serialize((Double)o, sb);
        }

        /// <summary>
        /// Converts an IJSONObject into an NET object.
        /// </summary>
        /// <param name="o">The IJSONObject object to convert.</param>
        /// <param name="t"></param>
        /// <returns>Returns a .NET object.</returns>
        public override object Deserialize( IJavascriptObject o , Type t )
        {
            //return Enum.Parse(type, o.ToString());

            object enumValue = _SerializerService.Deserialize( o , Enum.GetUnderlyingType( t ) );

            if ( !Enum.IsDefined( t , enumValue ) )
                throw new ArgumentException( "Invalid value for enum of type '" + t.ToString() + "'." , "o" );

            return Enum.ToObject( t , enumValue );
        }

        /// <summary>
        /// Tries the serialize value.
        /// </summary>
        /// <param name="o">The o.</param>
        /// <param name="t">The t.</param>
        /// <param name="sb">The sb.</param>
        /// <returns></returns>
        public override bool TrySerializeValue( object o , Type t , StringBuilder sb )
        {
            if ( t.IsEnum )
            {
                _SerializerService.Serialize(Convert.ChangeType(o, Enum.GetUnderlyingType(t)), sb);
                return true;
            }

            return base.TrySerializeValue( o , t , sb );
        }

        /// <summary>
        /// </summary>
        /// <param name="jso"></param>
        /// <param name="t"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        public override bool TryDeserializeValue( IJavascriptObject jso , Type t , out object o )
        {
            if ( t.IsEnum )
            {
                o = this.Deserialize( jso , t );
                return true;
            }

            return base.TryDeserializeValue( jso , t , out o );
        }
    }
}
